package deng.spring.userwebapp.services.plainhibernate;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import deng.spring.userwebapp.dal.CrudDao;

/**
 * A CrudDao base class that uses plain Hibernate Session API, and to provide subclass with the SessesionFactory access.
 * 
 * Note this impl will not use any Spring classes.
 * 
 * @author Zemian
 *
 * @param <E>
 * @param <K>
 */
public abstract class AbstractHibernateCrudDao<E, K extends Serializable> implements CrudDao<E, K> {

	protected Logger logger = LoggerFactory.getLogger(HibernateUserService.class);
	
	private SessionFactory sessionFactory;
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	private Class<E> entityClass;
	public Class<E> getEntityClass() {
		return entityClass;
	}

	public AbstractHibernateCrudDao() {
		// Get the class object from the entity generic type parameter
		Type entityType = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		@SuppressWarnings("unchecked")
		Class<E> entityTypeClass = (Class<E>)entityType;
		this.entityClass = entityTypeClass;
	}
	
	protected Session getSession() {
		Session session = sessionFactory.getCurrentSession();
		logger.trace("Obtained current Hibernate session: " + session);
		return session;
	}
		
	@Override
	public void create(E entity) {
		getSession().persist(entity);
	}
	
	@Override	
	public E read(K key) {
		@SuppressWarnings("unchecked")
		E entity = (E)getSession().get(entityClass, key);
		return entity;
	}

	@Override
	public void update(E entity) {
		getSession().update(entity);
	}

	@Override
	public void delete(K key) {
		Session session = getSession();
		@SuppressWarnings("unchecked")
		E entity = (E)session.load(entityClass, key);
		session.delete(entity);
	}

}
